package com.cf.holder

import android.app.Activity
import android.app.Application
import android.content.Context
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.MutableLiveData
import com.cf.annotation.Holder
import com.chad.library.adapter4.BaseQuickAdapter
import com.lau.holder.R

open class QuickAdapter : BaseQuickAdapter<Any, BaseHolder<*>> {
    private var adapterContext: AdapterContext
        set(value) {
            field = value
            field.setAdapter(this)
        }
    private var mHolderBuilderMap: HashMap<Int, IHolderBuilder<*>> = hashMapOf()
    val mFooterData: FooterHolder.Data = FooterHolder.Data()

    constructor(a: AdapterContext) {
        adapterContext = a
    }

    constructor(activity: Activity) {
        adapterContext = activity.toAdapterContext()
    }

    constructor(fragment: Fragment) {
        adapterContext = fragment.toAdapterContext()
    }

    fun addData(data: List<*>?) {
        data ?: return
        super.addAll(data as Collection<Any>)
    }

    fun setData(data: List<*>?) {
        submitList(data as List<Any>)
    }

    fun <H : IHolderBuilder<*>> addHolder(holder: H, key: Int? = null) {
        mHolderBuilderMap[key ?: holder.itemType()] = holder
    }

    override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): BaseHolder<*> {
        if (mHolderBuilderMap.containsKey(viewType)) {
            var holderClass = mHolderBuilderMap[viewType]
            holderClass?.let {
                return holderClass.createVH(parent).also { holder ->
                    holder.adapterContext = adapterContext
                }
            }
        }
        // If error return empty holder
        return BaseHolder.getEmptyHolder(parent)
    }

    override fun onBindViewHolder(holder: BaseHolder<*>, position: Int, item: Any?) {
        val item = getItem(position)
        item?.let {
            holder.mAdapterCount = getRealItemCount()
            holder.setData(item)
        }
    }

    fun getData(): List<Any> {
        return items
    }


    open fun getRealItemCount(): Int {
        return items.size
    }

    override fun getItemViewType(position: Int, list: List<Any>): Int {
        val item = getItem(position)
        return if (item is MultipleData) {
            item.itemType()
        } else {
            item?.javaClass?.hashCode() ?: -1
        }
    }
}

@Holder("item_footer")
open class FooterHolder @JvmOverloads constructor(
    parent: ViewGroup?,
    layoutId: Int = R.layout.item_footer
) : BaseHolder<FooterHolder.Data>(parent, layoutId) {
    var height = 0

    init {
        height = itemView.layoutParams.height
    }

    override fun convert(data: Data) {
        observe(data)
        itemView.layoutParams.height = if (data.isLoading) height else 0
        itemView.layoutParams = itemView.layoutParams
    }

    private var hasObserve = false

    private fun observe(data: Data) {
        if (!hasObserve) {
            hasObserve = true
            mLifecycleOwner?.lifecycle?.let {
                data.liveData.observe({ it }, {
                    refresh()
                })
            }
        }
    }

    override fun itemSize(): Int {
        return 0
    }

    class Data {
        var isLoading: Boolean = false
            set(value) {
                field = value
                liveData.value = this
            }

        var text: String? = ""
            set(value) {
                field = value
                liveData.value = this
            }
        val liveData: MutableLiveData<Data> = MutableLiveData()
    }
}

interface AdapterContext {
    fun activity(): Activity?

    /**
     * 使用adapter的宿主
     * activity, fragment等
     */
    fun target(): Any

    fun <T> targetAs2(): T?

    fun adapter(): QuickAdapter

    fun setAdapter(adapter: QuickAdapter)
}

abstract class BaseAdapterContext : AdapterContext {
    private lateinit var _adapter: QuickAdapter

    override fun <T> targetAs2(): T? {
        return target() as? T
    }

    override fun adapter(): QuickAdapter {
        return this._adapter
    }

    override fun setAdapter(adapter: QuickAdapter) {
        this._adapter = adapter
    }
}

fun Activity.toAdapterContext(): AdapterContext {
    return object : BaseAdapterContext() {
        override fun target(): Any {
            return this@toAdapterContext
        }

        override fun activity(): Activity {
            return this@toAdapterContext
        }
    }
}

fun Fragment.toAdapterContext(): BaseAdapterContext {
    return object : BaseAdapterContext() {
        override fun target(): Any {
            return this@toAdapterContext
        }

        override fun activity(): Activity? {
            return this@toAdapterContext.activity
        }
    }
}

fun Application.toAdapterContext(): BaseAdapterContext {
    return object : BaseAdapterContext() {
        override fun target(): Any {
            return this@toAdapterContext
        }

        override fun activity(): Activity? {
            return null
        }
    }
}

interface MultipleData {
    fun itemType(): Int
}